home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 5 / QRZ Ham Radio Callsign Database - Volume 5.iso / files / amiga / csrc720j.lzh / mbutil.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-02-02  |  20.9 KB  |  1,091 lines

  1. /*
  2.  *  MBUTIL.C - 9/08/92 - Utility functions.
  3.  */
  4.  
  5. #include "mb.h"
  6. #ifndef MCH_AMIGA
  7. #include "samapi.h"
  8. #endif
  9.  
  10. #ifdef MCH_AMIGA
  11. extern char tmpstr[];
  12. extern short debug;
  13. #endif
  14.  
  15. static char *onoff[2] = { "off", "on" };
  16.  
  17. /*
  18.  *  ! Command: Do DOS command ...
  19.  */
  20.  
  21. dosys()
  22. {
  23.   strcpy(tmp->scr, port->line + 2);
  24.   remnl(tmp->scr);
  25. #ifndef MCH_AMIGA
  26.   if (system(tmp->scr)) perror("Error");
  27. #else
  28.    /* Workaround MANX problem */
  29.   if (do_system(&tmp->scr[0])) perror("Error");
  30. #endif
  31. }
  32.  
  33.  
  34. /*
  35.  *  Sort utility.
  36.  *  base is the start of the array of items.
  37.  *  n is the number of items.
  38.  *  w is the item size.
  39.  *  t is scratch space the size of one item.
  40.  */
  41.  
  42. sort(base, n, w, t)
  43. char *base;
  44. int   n;
  45. int   w;
  46. char *t;
  47. {
  48.   register int i;
  49.   register int j;
  50.   register int g;
  51.   char *p1, *p2;
  52.  
  53.   for (g = n/2; g; g /= 2)
  54.   for (i = g; i < n; i++)
  55.   for (j = i - g; j >= 0; j -= g)
  56.   {
  57.     p1 = base + (w * j);
  58.     p2 = base + (w * (j + g));
  59.  
  60.     if (strncmp(p1, p2, w) <= 0) break;
  61.     memcpy(t, p1, w);
  62.     memcpy(p1, p2, w);
  63.     memcpy(p2, t, w);
  64.   }
  65. }
  66.  
  67. /*
  68.  *  Return number of days between two dates.
  69.  */
  70.  
  71. ddiff(fr, to, flag)
  72. char fr[], to[];
  73. int flag;
  74. {
  75.   register int d=0;
  76.   static short dpm[13] =
  77.   { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
  78.  
  79.   if(flag)
  80.     d = 365 * (10 * (to[0] - fr[0]) + to[1] - fr[1]);
  81.  
  82.   d += (dpm[10 * (to[2] - '0') + to[3] - '0'] -
  83.    dpm[10 * (fr[2] - '0') + fr[3] - '0']);
  84.  
  85.   d += 10 * (to[4] - fr[4]) + to[5] - fr[5];
  86.  
  87.   return d;
  88. }
  89.  
  90.  
  91. /*
  92.  *  Wild card match of callsigns with ? and * in first arg.
  93.  */
  94.  
  95. wcm(s1, s2)
  96. char *s1, *s2;
  97. {
  98.   register short l;
  99.  
  100.   if (*s1 is '*') if (matchn(s2, cport->user->call, ln_call)) return false;
  101.  
  102.   for (l = 0; l < ln_call; l++, s1++, s2++)
  103.   {
  104.     switch(*s1)
  105.     {
  106.        case '*' : return true;
  107.        case '!' : if (!isdigit(*s2)) return false;
  108.        case '?' : break;
  109.  
  110.        default  : if (*s1 isnt *s2) return false;
  111.     }
  112.   }
  113.   return true;
  114. }
  115.  
  116. /*
  117.  *  Save remote sysop command, for later execution.
  118.  */
  119.  
  120. savecmd()
  121. {
  122.   strcpy(scmd, port->line);
  123.   s_param setbit s_cmd;
  124.   port->msg = mdone;
  125. }
  126.  
  127. /*
  128.  *  EP command: change port parameters.
  129.  */
  130.  
  131. edport()
  132. {
  133.   register PORTS *p;
  134.   register int i;
  135.  
  136.   if ((p = findport(*port->fld[1])) is NULL) { port->msg = mnport; return; }
  137.  
  138.   sprintf(tmp->scr, "Change parameters for port %c, %s\n\n", p->id, p->name);
  139.   outstr(tmp->scr);
  140.  
  141.   while (true)
  142.   {
  143.     outstr("Bbs Down Up Gate Illegal Monitor Remote Xparent 1 2 3 Time Cdigi Fwd Error\n");
  144.  
  145.     sprintf(tmp->scr,"%c   %c    %c  %c    %c       %c       %c      %c       %c %c %c %-3d   %d    %-2d  %d\n",
  146.      (p->priv & p_bbs)/p_bbs +'0',
  147.      (p->priv & p_dnload)/p_dnload +'0', (p->priv & p_upload)/p_upload +'0',
  148.      (p->priv & p_gate)/p_gate +'0', (p->priv & p_ilcal)/p_ilcal +'0',
  149.      (p->priv & p_mon)/p_mon +'0', (p->priv & p_sysop)/p_sysop +'0',
  150.      p->tmode +'0',p->ecmon +'0', p->ecuser +'0', p->eccmds +'0',
  151.      p->ctime, p->ndigi, p->fwdmin, p->errmax);
  152.     outstr(tmp->scr);
  153.  
  154.     getcmd();
  155.     if (port->mode & gone) return;
  156.     i = atoi(port->fld[1]);
  157.     switch(port->opt1)
  158.     {
  159.       case 'B' : p->priv flipbit p_bbs;     break;
  160.       case 'C' : p->ndigi = i;              break;
  161.       case 'D' : p->priv flipbit p_dnload;  break;
  162.       case 'E' : p->errmax = i;             break;
  163.       case 'F' : p->fwdmin = i;             break;
  164.       case 'G' : p->priv flipbit p_gate;    break;
  165.       case 'I' : p->priv flipbit p_ilcal;   break;
  166.       case 'M' : p->priv flipbit p_mon;     break;
  167.       case 'R' : p->priv flipbit p_sysop;   break;
  168.       case 'T' : p->ctime = i;              break;
  169.       case 'U' : p->priv flipbit p_upload;  break;
  170.       case 'X' : p->tmode  = 1 - p->tmode;  break;
  171.       case '1' : p->ecmon  = 1 - p->ecmon;  break;
  172.       case '2' : p->ecuser = 1 - p->ecuser; break;
  173.       case '3' : p->eccmds = 1 - p->eccmds; break;
  174.       default  : if (!port->opt1) return;
  175.     }
  176.   }
  177. }
  178.  
  179. /*
  180.  *  ES command: change system parameters.
  181.  */
  182.  
  183. chgparam()
  184. {
  185.   register int i;
  186.  
  187.   while (true)
  188.   {
  189.     outstr("Bell Kill F&B-kill Svc-msg\n");
  190.     sprintf(tmp->scr, "%c    %c    %c        %c\n",
  191.       (s_param & s_page)/s_page+'0', (s_param & s_kill)/s_kill+'0',
  192.       (s_param & s_fkill)/s_fkill+'0', (s_param & s_svc)/s_svc+'0');
  193.     outstr(tmp->scr);
  194.  
  195.     getcmd();
  196.     if (port->mode & gone) return;
  197.     switch(port->opt1)
  198.     {
  199.       case 'B' : s_param flipbit s_page;  break;
  200.       case 'F' : s_param flipbit s_fkill; break;
  201.       case 'K' : s_param flipbit s_kill;  break;
  202.       case 'S' : s_param flipbit s_svc;   break;
  203.       default  : if(!port->opt1) return;
  204.     }
  205.   }
  206. }
  207.  
  208. /*
  209.  *  Screen paging.
  210.  */
  211.  
  212. char *pausemsg;
  213. static char *pghdr = NULL;
  214. static short lnmax;
  215. static short lncnt;
  216.  
  217. /*
  218.  *  If local console, pause until user types a character.
  219.  *  Return the character.
  220.  *  If not local console, just return a blank.
  221.  */
  222.  
  223. #ifndef MCH_AMIGA
  224. char pause()
  225. {
  226.   register char t;
  227.  
  228.   if (port->user->state & u_pause) return ' ';
  229.   if (!pt_flag and ((port->mode is local) or (port->opt1 is 'L')))
  230.   {
  231.     prtx(pausemsg);
  232.     if (port->mode isnt local)
  233.     {
  234.       outchar('\n');
  235.       while (!getdat());
  236.       t = *port->line;
  237.     }
  238.     else
  239.     {
  240.       t = inchar();
  241.       outchar ('\n');
  242.     }
  243.     return toupper(t);
  244.   }
  245.   return ' ';
  246. }
  247. #endif
  248.  
  249. /*
  250.  *  Start screen paging.
  251.  */
  252.  
  253. pgst(cp)
  254. char *cp;
  255. {
  256. #ifndef MCH_AMIGA
  257.   if ((pghdr = cp) is NULL) lnmax = 23; else lnmax = 22;
  258.   lncnt = lnmax;
  259. #else
  260.    lnmax = lncnt = 22;
  261. #endif
  262. }
  263.  
  264. /*
  265.  *  Pause if full screen.
  266.  */
  267.  
  268. char pgck()
  269. {
  270.   if (--lncnt) return ' ';
  271.   lncnt = lnmax;
  272.   return pause();
  273. }
  274.  
  275. /*
  276.  *  Display header if at top of screen.
  277.  */
  278.  
  279. pghd()
  280. {
  281.   if (lncnt is lnmax) if (pghdr isnt NULL) outstr(pghdr);
  282. }
  283.  
  284. /*
  285.  *  Pause if required at last line.
  286.  */
  287.  
  288. pgdn()
  289. {
  290.   if (lncnt isnt lnmax) pause();
  291. }
  292.  
  293. /*
  294.  *  Display "no such file" message, and file name.
  295.  */
  296.  
  297. nofile(c)
  298. char *c;
  299. {
  300.   prtx(mnfile); outstr(c); outchar('\n');
  301. }
  302.  
  303. /*
  304.  *  Memory allocation problem, just plain quit.
  305.  */
  306.  
  307. #ifndef MCH_AMIGA
  308. errall()
  309. {
  310.   outstr("Not enough memory\n");
  311.   exit (0);
  312. #else
  313. errall(i)
  314. int i;
  315. {
  316.   printf("Not enough memory - %d\n",i);
  317.   done(1);
  318. #endif
  319. }
  320.  
  321. /*
  322.  *  Is this a callsign?
  323.  */
  324.  
  325. iscall(c)
  326. char *c;
  327. {
  328.   register short i, ld, nd;
  329.  
  330.   nd = 0;
  331.   for (i = 0; (i < ln_call) and (*c isnt ' '); i++, c++)
  332.   {
  333.     if (ld = isdigit(*c)) nd++;
  334.   }
  335.   return ((i > 3) and ((nd is 1) or (nd is 2)) and !ld);
  336. }
  337.  
  338. /*
  339.  *  Print list of ports and port names.
  340.  */
  341.  
  342. shports()
  343. {
  344.   register PORTS *p;
  345.  
  346.   sprintf(port->line, "Use %c and port ID:\n", port->opt1);
  347.   outstr(port->line);
  348.   for (p = porthd; p isnt NULL; p = p->next)
  349.   {
  350.     sprintf(port->line, "%c%c  %s\n", port->opt1, p->id, p->name);
  351.     outstr(port->line);
  352.   }
  353. }
  354.  
  355. /*
  356.  *  Return pointer to port with id pid, or NULL.
  357.  */
  358.  
  359. PORTS *findport(pid)
  360. char pid;
  361. {
  362.   register PORTS *p;
  363.  
  364.   for (p = porthd; p isnt NULL; p = p->next) if (p->id is pid) return p;
  365.   return NULL;
  366. }
  367.  
  368. /*
  369.  *  Is it?
  370.  */
  371.  
  372. iseof(cp)
  373. char *cp;
  374. {
  375.   return match(cp, "*** EOF\n");
  376. }
  377.  
  378. /*
  379.  *  Remove new line  and control characters from end of string.
  380.  */
  381.  
  382. remnl(p)
  383. char *p;
  384. {
  385.   for (; *p; p++)
  386.   {
  387.     if (*p is '\n') { *p = '\0'; return; }
  388.     if (*p < ' ') *p = ' ';
  389.   }
  390. }
  391.  
  392. /*
  393.  *  Parse a callsign.
  394.  *  Blank pad the output field, remove trailing ssid from call.
  395.  *  Return the SSID.
  396. */
  397.  
  398. pcall(c, p)
  399. char *c;
  400. char *p;
  401. {
  402.   register short i;
  403.  
  404. /*
  405.  *  Blank fill the target buffer.
  406.  */
  407.  
  408.   fill (c, ' ', ln_call);
  409.  
  410. /*
  411.  *  Ignore leading spaces.
  412.  */
  413.  
  414.   while (*p and (*p is ' ')) p++;
  415.  
  416. /*
  417.  *  Copy the call from the string into the call buffer.
  418.  */
  419.  
  420.   for (i = ln_call; i and *p; i--)
  421.   {
  422.     if (*p <= ' ') return 0;
  423. #ifdef MCH_AMIGA
  424. /* handle strange things from the KAM */
  425.     if(*p == '/')return 0;
  426. #endif
  427.     if (*p is '-') return atoi(++p);
  428.     if (*p is '.') return 0;
  429. #ifndef MCH_AMIGA
  430.     *c++ = *p++;
  431. #else
  432.     *c++ = toupper(*p++);
  433. #endif
  434.   }
  435.   if (*p++ is '-') return atoi(p); else return 0;
  436. }
  437.  
  438. /*
  439.  *  Is the string a number?
  440.  */
  441.  
  442. num(p)
  443. char *p;
  444. {
  445.   for (; *p; p++) if (!isdigit(*p)) return false;
  446.   return true;
  447. }
  448.  
  449. /*
  450.  *  "Output, no blanks".
  451.  */
  452.  
  453. outnb(p, n)
  454. char *p;
  455. short n;
  456. {
  457.   while (n--) switch (*p)
  458.   {
  459.     case ' ' :
  460.     case '\n' :
  461.     case '\0' : return;
  462.     default: outchar(*p++);
  463.   }
  464. }
  465.  
  466. /*
  467.  *  Print a number right justified in a fixed width field.
  468.  */
  469.  
  470. outnr(i, n)
  471. int   i;  /* The number to print */
  472. short n;  /* Field width */
  473. {
  474.   char num[7];
  475.  
  476.   sprintf (num, "%-6u", i);
  477.   outnb (num, n);
  478. }
  479.  
  480. /*
  481.  *  Display software version.
  482.  */
  483.  
  484. prtver()
  485. {
  486.   outstr(ver);
  487. }
  488.  
  489. /*
  490.  *  Print multi-line message.
  491.  */
  492.  
  493. prtm(m)
  494. MLM *m;
  495. {
  496.   register MLM *p;
  497.  
  498.   for (p = m; p isnt NULL; p = p->next) prtx(p->text);
  499. }
  500.  
  501. /*
  502.  *  Print a string, expanding the "$" fields.
  503.  */
  504.  
  505. #ifndef MCH_AMIGA
  506. prtx(p)
  507. char *p;
  508. {
  509.  
  510.   for (; *p; p++)
  511.   {
  512.     if (*p isnt '$') outchar(*p);
  513.     else switch (*(++p))
  514.     {
  515.       case 'A' : outnb(port->mmhs->bbs, ln_call); break;
  516.       case 'B' : outchar(port->mmhs->type); break;
  517.       case 'C' : outnr(mfhs->next_msg, 5); break;
  518.       case 'D' : outstr(l_date); break;
  519.       case 'E' : outstr(port->mmhs->title); break;
  520.       case 'F' : outstr(port->lport->name); break;
  521.       case 'G' : outnb(port->mmhs->to, ln_call); break;
  522.       case 'H' : p++; break;
  523.       case 'I' : outnb(port->user->handle, ln_handle); break;
  524.       case 'J' : outnb(port->mmhs->date, ln_date); break;
  525.       case 'K' : outnb(port->mmhs->time, ln_time); break;
  526.       case 'L' : outnr(mfhs->next_msg - 1, 5); break;
  527.       case 'M' : outnr(port->mmhs->number, 5); break;
  528.       case 'N' : outnr(mfhs->count, 4); break;
  529.       case 'O' : outnb(cport->user->call, ln_call); break;
  530.       case 'P' : outnb(port->mmhs->from, ln_call); break;
  531.       case 'Q' : outstr(qth); break;
  532.       case 'R' : outnb(port->rcall, ln_call); break;
  533.       case 'S' : outnb(port->lport->user->call, ln_call); break;
  534.       case 'T' : outnb(l_time, ln_time); break;
  535.       case 'U' : outnb(port->user->call, ln_call); break;
  536.       case 'V' : outstr(ver); break;
  537.       case 'W' : outnb(port->lport->user->handle, ln_handle); break;
  538.       case 'X' : outnb(port->user->date, ln_date); break;
  539.       case 'Y' : outnb(port->user->time, ln_time); break;
  540.       case 'Z' : outnr(port->user->msg_number, 5); break;
  541.       case 'a' : outstr(orgbbs); break;
  542.       case 'h' : outstr(port->mmhs->call); break;
  543.       case 'j' : outstr(orgdate); break;
  544.       case 'k' : outstr(orgtime); break;
  545.       case 'm' : outstr(orgmsg); break;
  546.       default  : outchar(*p);
  547.     }
  548.   }
  549. }
  550. #else
  551.  
  552. /* Faster version of prtx. One char at a time is really painful! */
  553. /* Make sure that if prtx changes in later versions this version is
  554.    also changed!!!!!
  555.  
  556.    This routine uses tmpstr to build up the string. Therefore there can
  557.    be no other use made of tmpstr (e.g. for debugging).
  558.  
  559.    There's also a mod for fbb so that if there's a LF in the string it is
  560.    mapped into CR/LF and also the string is left in tmpstr and not written
  561.    out to the TNC.
  562.  
  563. */
  564. extern char fbb_flag = 0;
  565. unsigned char *op;
  566. prtx(p)
  567. unsigned char *p;
  568. {
  569.    register unsigned char *ip;
  570.    register PORTS *pp;
  571.  
  572.    pp = port;
  573.  
  574.    op = (unsigned char *) &tmpstr[0];
  575.    for(ip=p; *ip; ip++) {
  576.       if(*ip isnt '$') {
  577.          if(fbb_flag && (*ip == '\n'))*op++ = '\r';
  578.          *op++ = *ip;
  579.       }
  580.       else switch (*(++ip)) {
  581.       case 'A':
  582.          /* For FBB WE MUST put out a BBS. So if there isn't one in the
  583.             header then make it the bbs we are forwarding to
  584.          */
  585.          if(fbb_flag) {
  586.             if(*pp->mmhs->bbs == ' ') {
  587.                xoutnb(pp->user->call,ln_call);
  588.                break;
  589.             }
  590.          }
  591.          xoutnb(pp->mmhs->bbs, ln_call);
  592.          break;
  593.       case 'B' : *op++ = pp->mmhs->type; break;
  594.       case 'C' : xoutnr(mfhs->next_msg, 5); break;
  595.       case 'D' : xoutstr(l_date); break;
  596.       case 'E' : xoutstr(pp->mmhs->title); break;
  597.       case 'F' : xoutstr(pp->lport->name); break;
  598.       case 'G' : xoutnb(pp->mmhs->to, ln_call); break;
  599.       case 'H' : ip++; break;
  600.       case 'I' : xoutnb(pp->user->handle, ln_handle); break;
  601.       case 'J' : xoutnb(pp->mmhs->date, ln_date); break;
  602.       case 'K' : xoutnb(pp->mmhs->time, ln_time); break;
  603.       case 'L' : xoutnr(mfhs->next_msg - 1, 5); break;
  604.       case 'M' : xoutnr(pp->mmhs->number, 5); break;
  605.       case 'N' : xoutnr(mfhs->count, 4); break;
  606.       case 'O' : xoutnb(cport->user->call, ln_call); break;
  607.       case 'P' : xoutnb(pp->mmhs->from, ln_call); break;
  608.       case 'Q' : xoutstr(qth); break;
  609.       case 'R' : xoutnb(pp->rcall, ln_call); break;
  610.       case 'S' : xoutnb(pp->lport->user->call, ln_call); break;
  611.       case 'T' : xoutnb(l_time, ln_time); break;
  612.       case 'U' : xoutnb(pp->user->call, ln_call); break;
  613.       case 'V' : xoutstr(ver); break;
  614.       case 'W' : xoutnb(pp->lport->user->handle, ln_handle); break;
  615.       case 'X' : xoutnb(pp->user->date, ln_date); break;
  616.       case 'Y' : xoutnb(pp->user->time, ln_time); break;
  617.       case 'Z' : xoutnr(pp->user->msg_number, 5); break;
  618.       case 'a' : xoutstr(orgbbs); break;
  619. case 'b':        xoutnb(pp->mmhs->bid,ln_bid); break;
  620.       case 'h' : xoutstr(pp->mmhs->call); break;
  621.       case 'j' : xoutstr(orgdate); break;
  622.       case 'k' : xoutstr(orgtime); break;
  623.       case 'm' : xoutstr(orgmsg); break;
  624. case 's':        xoutnr(pp->mmhs->size); break;
  625.       default  : *op++ = *ip;
  626.       }
  627.    }
  628.    *op = 0;
  629.    if(!fbb_flag)outstr(&tmpstr[0]);
  630. }
  631.  
  632. xoutstr(s)
  633. unsigned char *s;
  634. {
  635.    while(*s)*op++ = *s++;
  636. }
  637.  
  638.  
  639. /*
  640.  *  "Output, no blanks".
  641.  */
  642.  
  643.  
  644. xoutnb(p, n)
  645. char *p;
  646. short n;
  647. {
  648.   while (n--) switch (*p)
  649.   {
  650.     case ' ' :
  651.     case '\n' :
  652.     case '\0' : return;
  653.     default: *op++ = *p++;
  654.   }
  655. }
  656.  
  657. /*
  658.  *  Print a number right justified in a fixed width field.
  659.  */
  660.  
  661. xoutnr(i, n)
  662. int   i;  /* The number to print */
  663. short n;  /* Field width */
  664. {
  665.   char num[7];
  666.  
  667.    sprintf(num,"%-6u",i);
  668.    xoutnb (num, n);
  669. }
  670. #endif
  671.  
  672. /*
  673.  *  Write random record.
  674.  */
  675.  
  676. write_rec(fid, rec, buffer)
  677. int fid;
  678. int rec;
  679. char buffer[];
  680. {
  681. #ifndef MCH_AMIGA
  682.   long lseek();
  683. #endif
  684.   long offs;
  685.  
  686.   offs = (long)rec * (long)RECSIZE;
  687.   lseek(fid, offs, 0);
  688.   return (write(fid, buffer, RECSIZE) is RECSIZE);
  689. }
  690.  
  691. /*
  692.  *  Read random record.
  693.  */
  694.  
  695. read_rec(fid, rec, buffer)
  696. int fid;
  697. int rec;
  698. char buffer[];
  699. {
  700. #ifndef MCH_AMIGA
  701.   long lseek();
  702. #endif
  703.   long offs;
  704.  
  705.   offs = (long)rec * (long)RECSIZE;
  706.   lseek(fid, offs, 0);
  707.   return (read(fid, buffer, RECSIZE) is RECSIZE);
  708. }
  709.  
  710. /*
  711.  *  Fill buffer with characters from the current input,
  712.  *  until CR or buffer overflow. Terminate buffer with
  713.  *  '\0', thus making it a string.
  714.  *  Translate \r to \n.
  715.  *  Ignore \n.
  716.  *  Deal with backspace and things like that.
  717.  *  Set flags for timeout and disconnect.
  718.  */
  719.  
  720. #ifndef MCH_AMIGA
  721. getdat()
  722. {
  723.   register char *cp;
  724.   register PORTS *p;
  725.   register char ch;
  726.  
  727.   p = port;
  728.  
  729.   if (p->flags & p_dotmr)
  730.   {
  731.     if ((p->mode & idle) and (p->dev is p_tnc)) settmr(&p->itime, 2);
  732.     else settmr(&p->itime, p->ctime);
  733.   }
  734.  
  735.   p->flags setbit p_dotmr;
  736.   cp = p->line;
  737.  
  738.   while (true)
  739.   {
  740.     while(!instat())
  741.     {
  742.       if (p isnt cport)
  743.       {
  744.    ioport(cport);
  745.    if (instat())
  746.    {
  747.      ch = inchar();
  748.  
  749.      if (ch is achar)
  750.      {
  751.        p->mode = forced;
  752.        ioport(p);
  753.        return true;
  754.      }
  755.  
  756.      if (ch is tchar)
  757.      {
  758.        p->flags setbit p_opreq;
  759.        ioport(p);
  760.        return true;
  761.      }
  762.  
  763.    }
  764.    ioport(p);
  765.       }
  766.       if (p->flags & p_trans)
  767.       if (!isdcd())
  768.      {
  769.      if (!(p->mode & idle)) p->mode = discon;
  770.      return true;
  771.      }
  772.  
  773.       if (!chktmr(p->itime))
  774.       {
  775.    *cp = '\0';
  776.    if (!(p->mode & idle)) p->mode = timeout;
  777.    return true;
  778.       }
  779.     }
  780.  
  781.     *cp = inchar();
  782.  
  783. /*
  784.  *  Got a character, deal with it.
  785.  */
  786.  
  787.     if ((cp is (p->line + linelen - 2)) or (*cp is '\r'))
  788.     {
  789. /*
  790.  *  Got a whole line. Either buffer full, or character is CR.
  791.  */
  792.       if (*cp is '\r') *cp = '\n';
  793.       cp++; *cp = '\0';
  794.  
  795.       if (p->flags & p_echo) outchar('\n');
  796.       if (!(p->flags & p_trans))
  797.       {
  798.     if (isdis(p->line))
  799.     {
  800.       if (!(p->mode & idle)) p->mode = discon;
  801.       return true;
  802.     }
  803.     if (isretry(p->line)) return false;
  804.  
  805.     if (isreq(p->line))
  806.     {
  807.       p->flags setbit p_req;
  808.       pcall(p->rcall, p->line + 20);
  809.       p->flags clrbit p_dotmr;
  810.       return false;
  811.     }
  812.       }
  813.       return true;
  814.     }
  815.  
  816. /*
  817.  *  Not end of line.
  818.  *  Stuff the character in the buffer.
  819.  *  Handle some control characters. Ignore some.
  820.  */
  821.  
  822.     switch(*cp)
  823.     {
  824.       default   : if (p->flags & p_echo) outchar(*cp); cp++; break;
  825.       case '\b' :
  826.    if (cp > p->line) { cp--; if (p->flags & p_echo) outstr("\b \b"); }
  827.    break;
  828.  
  829.       case '\n' : if (cp is p->line) { *cp = '\0'; return false; }
  830.       case '\0' : ;   /* Ignore most ctl char */
  831.       case ctl_c: ;   /* Ignore most ctl char */
  832.       case ctl_v: ;   /* Ignore most ctl char */
  833.     }
  834.   }
  835. }
  836. #endif
  837.  
  838. /*
  839.  *  Is the string a header line?
  840.  */
  841.  
  842. ishead(p)
  843. char *p;
  844. {
  845.   if (!*p or (*p is '\n')) return false;      /* end of headers */
  846.   if (matchn(p, "R:" ,2)) return true;
  847.   return false;
  848. }
  849.  
  850. /*
  851.  *  Parse a command line.
  852.  *
  853.  *  Input:   Line of text in port->line.
  854.  *  Returns: Fields are placed in port->cmd.
  855.  *           Fields are pointed to by port->fld[].
  856.  *           port->flds is set to the number of fields found.
  857.  *           Each field is null-terminated.
  858.  *           Fields beyond maxflds are ignored.
  859.  */
  860.  
  861. #ifndef MCH_AMIGA
  862. parse()
  863. {
  864.   register short bl;
  865.   register char *in, *out;
  866.  
  867.   for (port->flds = 0; port->flds < maxflds;)
  868.     port->fld[port->flds++] = nullstr;
  869.  
  870.   in  = port->line;
  871.   out = port->cmd;
  872.   bl  = false;
  873.   port->flds = 0;
  874.  
  875.   while (*in and (port->flds < maxflds) and (out < (port->cmd + cmdlen - 1)))
  876.   {
  877.     *out = toupper(*in);
  878.     if (bl)
  879.     {
  880.       if ((*in <= ' ') or ((*in is '@') and (port->flds is 2)))
  881.       {
  882.    bl = false;
  883.    *out = '\0';
  884.    if (*in is '@')
  885.    {
  886.      out++;
  887.      *out = '@';
  888.      port->fld[port->flds++] = out++;
  889.      *out = '\0';
  890.    }
  891.       }
  892.       out++;
  893.     }
  894.     else
  895.     {
  896.       if (*in > ' ')
  897.       {
  898.    bl = true;
  899.    port->fld[port->flds++] = out++;
  900.    if ((*in is '@') and (*(in+1) > ' '))
  901.    {
  902.      bl = false;
  903.      *out++ = '\0';
  904.    }
  905.       }
  906.     }
  907.     in++;
  908.   }
  909.   *out = '\0';
  910.  
  911.   port->opt1 = *port->fld[0];
  912.   port->opt2 = *(port->fld[0] + 1);
  913.   if (!port->opt2) port->opt2 = ' ';
  914. }
  915. #endif
  916.  
  917. /*
  918.  *  Bundle getdat and parse.
  919.  */
  920.  
  921. getcmd()
  922. {
  923.   while(!getdat());
  924.   parse();
  925. }
  926.  
  927. /*
  928.  *  Fill some memory with a character.
  929.  */
  930.  
  931. fill(adr, ch, len)
  932. char *adr;
  933. char ch;
  934. int len;
  935. {
  936.   while (len--) *adr++ = ch;
  937. }
  938.  
  939. /*
  940.  *  Copy C string to LJSF string.
  941.  */
  942.  
  943. ljsf(to, from, size)
  944. char *to;
  945. char *from;
  946. int  size;
  947. {
  948.   fill(to, ' ', size);
  949.   while (size--)
  950.   {
  951. #ifndef MCH_AMIGA
  952.     if (*from < ' ') return;
  953. #else
  954. /* My code in the FBB routines requires that ljsf treats a blank as the end
  955.    of the string (which it is)
  956. */
  957.     if (*from <= ' ') return;
  958. #endif
  959.     *to++ = *from++;
  960.   }
  961. }
  962.  
  963. /*
  964.  *  Copy LJSF string to C string.
  965.  */
  966.  
  967. unbl(to, from, size)
  968. char *to, *from;
  969. int size;
  970. {
  971.   while (size--)
  972.   {
  973.     if (*from <= ' ') { *to = '\0'; return; }
  974.     *to++ = *from++;
  975.   }
  976.   *to = '\0';
  977. }
  978.  
  979. /*
  980.  *  Are you sure? .....
  981.  */
  982. sure()
  983. {
  984.   outstr("Are you sure (Y/N)?\n");
  985.   while (!getdat());
  986.   if (toupper(*port->line) is 'Y') return false;
  987.   return true;
  988. }
  989.  
  990. /* Search string for match */
  991.  
  992. search(a,b,c)
  993. char *a, *b;
  994. int c;
  995. {
  996.   for( ; *a; a++)
  997.     if (matchn(a, b, c)) return true;
  998.   return false;
  999. }
  1000. #ifndef MCH_AMIGA
  1001.  
  1002. /***********************************************************
  1003.  * findcall additions for Sam Lookup.
  1004.  * returns if error, Displays call if call found
  1005.  ***********************************************************/
  1006.  
  1007. int LocateSam(void);
  1008. int CallSam(int cmd, void far *cmdbuf, void far *rspbuf);
  1009. void display_call(datarec_t * d);
  1010.  
  1011.  
  1012. find_call()
  1013. {
  1014.   int err;
  1015.   cmdfindcall_t sam_in;   /* buffer for samapi find command */
  1016.   rspdatarec_t sam_out;   /* buffer for result of samapi find command */
  1017.  
  1018.   /*
  1019.    * make sure the resident code (SAMAPI.EXE) has been installed
  1020.    */
  1021.  
  1022.   if (LocateSam())
  1023.   {
  1024.      printf("*** SAMAPI not loaded\n");
  1025.      return;
  1026.   }
  1027.  
  1028.   /*
  1029.    * build command block and call SAMAPI, function SamFindCall
  1030.    */
  1031.  
  1032.   sam_in.packflags = 0;   /* 0 to unpack all data record fields */
  1033.   strncpy(sam_in.call, port->fld[1], 6);
  1034.   sam_in.call[6] = 0;
  1035.   if(s_flag & s_dv) begin_lock();
  1036.   err = CallSam(SamFindCall, &sam_in, &sam_out);
  1037.   if (s_flag & s_dv) end_lock();
  1038.   /*
  1039.    * check for unusual error, something other than not found
  1040.    */
  1041.  
  1042.   if (err != 0 and err != SerrNotFound)
  1043.   {
  1044.      sprintf(port->line, "*** SAMAPI error %d\n", err);
  1045.      outstr(port->line);
  1046.      return;
  1047.   }
  1048.  
  1049.   /*
  1050.    * check for just not found
  1051.    */
  1052.  
  1053.   if (err is SerrNotFound)
  1054.   {
  1055.      outstr("*** Call not found\n");
  1056.      return;
  1057.   }
  1058.  
  1059.   /*
  1060.    * got a match, display the call data
  1061.    */
  1062.  
  1063.   display_call(&sam_out.d);
  1064.   log('U', 'C', 'B', port->fld[1]);
  1065.   return;
  1066. }
  1067.  
  1068. /********************************************************
  1069.  * display_call
  1070.  *
  1071.  * input is pointer to data record, returns nothing
  1072.  ********************************************************/
  1073.  
  1074. void display_call(datarec_t * d)
  1075. {
  1076.   sprintf(port->line, "%s ", d->FirstName);
  1077.   outstr(port->line);
  1078.   if (d->MidInitial[0] != ' ')
  1079.   {
  1080.     sprintf(port->line, "%s ", d->MidInitial);
  1081.     outstr(port->line);
  1082.   }
  1083.   sprintf(port->line, "%s  %s  %s\n", d->LastName, d->Call, d->Class);
  1084.   outstr(port->line);
  1085.   sprintf(port->line, "%s (%s)\n", d->Address, d->Dob);
  1086.   outstr(port->line);
  1087.   sprintf(port->line,"%s, %s %s\n", d->City, d->State, d->Zip);
  1088.   outstr(port->line);
  1089. }
  1090. #endif
  1091.